package flextv.main.logic.download {

import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;

import flextv.core.download.IDownloadable;
import flextv.core.download.WatchId2FlvUrlConverter;
import flextv.core.logic.Logger;
import flextv.core.logic.ResponderAdapter;

import mx.controls.Alert;
import mx.logging.ILogger;
import mx.utils.ObjectUtil;
	

internal class DownloadDelegate {
	
	private static const LOG: ILogger = Logger.getLog(DownloadDelegate);
	
	private var _item: IDownloadable;
	
	private var _target: File;
	
	private var flvUrlLoader: URLLoader;
	
	private var _fnResult: Function;
	
	public function DownloadDelegate(item: IDownloadable, target: File, fnResult: Function) {
		_item = item;
		_target = target;
		_fnResult = fnResult;
	}
	
	
	public function download(): void {
		this.flvUrlLoader = new URLLoader();
		this.flvUrlLoader.dataFormat = URLLoaderDataFormat.BINARY;
		this.flvUrlLoader.addEventListener(Event.COMPLETE, onFlvUrlLoaderComplete);
		this.flvUrlLoader.addEventListener(ProgressEvent.PROGRESS, onFlvUrlLoaderProgress);
		flvUrlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
		
		if(_item.fileUri != null) {
			this.startDownload(_item.fileUri);
		} else {
			new WatchId2FlvUrlConverter(_item, new ResponderAdapter(
				function(result: Object): void {
					startDownload((result as IDownloadable).fileUri);
				},
				function(faultInfo: Object): void {
					throw new Error(faultInfo.toString());
				}
			)).convert();
		}
	}
	
	private function onIOError(event: IOErrorEvent): void {
		LOG.warn(ObjectUtil.toString(event));
		Alert.show("Could not get additional data from network ("+event.errorID+")!", "Connection Error");
	}
	
	private function startDownload(flvUrl: String): void {
		if(_fnResult != null) {
			_fnResult();
		}
		
		LOG.debug("Loading flv request [" + flvUrl + "].");
		this.flvUrlLoader.load(new URLRequest(flvUrl));
	}
	

	private function onFlvUrlLoaderProgress(event: ProgressEvent): void {
		var percent: uint = Math.round((event.bytesLoaded / event.bytesTotal) * 100);
		if(percent == 100) {
			percent = 99;
		}
		_item.downloaded = percent;
	}
	
	
	private function onFlvUrlLoaderComplete(event: Event): void {
		const bytes: ByteArray = this.flvUrlLoader.data as ByteArray;
		const fs: FileStream = new FileStream();
		
		fs.openAsync(_target, FileMode.WRITE);   
		fs.writeBytes(bytes, 0, bytes.length);  
		fs.addEventListener(Event.CLOSE, function(event: Event): void {
			LOG.debug("Finished downloading file to [" + _target.nativePath + "].");
			_item.downloaded = 100;
		});
		
		fs.close();
	}
	
}
}